//
//  MYGChatController.swift
//  MYGrow
//
//  Created by 小火科技 on 2024/3/1.
//

import UIKit
import TZImagePickerController
import Guitar
import MJRefresh
import AVFoundation
import QMUIKit
import RZColorfulSwift
import IQKeyboardManagerSwift

class MYGChatController: MYGBaseController {
    // MARK: - Property
    private var sessionId: Int
    private let mobile: String
    private var mo_shenggx: Int
    private let socket = MYGSocketManager.shared
    private var functions: [MYGChatFunctionType] = [.image, .photo, .position, .message, .appoint]
    
    private var contents: [Any] = []
    
    private var chatHistoryModel: [MYGIMSingleChatModel] = []
    private var fastMessages: [MYGIMFastMessageModel] = []
    private var chatHistorys: [MYGIMSingleChatListData] {
        var array = [MYGIMSingleChatListData]()
    
        for model in chatHistoryModel {
            for message in model.message {
                array.append(contentsOf: message.data)
            }
        }
        
        return array
    }
    
    private var avatar: String = ""
    private var userName: String = ""
    
    private var emoji: MYGEmojiModel = MYGEmojiModel() {
        didSet {
            emojiCollectionView.reloadData()
        }
    }
    
    private var needScroll = true
    private var coordinate: CLLocationCoordinate2D?
    var recorder: AVAudioRecorder?
    var player: AVAudioPlayer?
    let session:AVAudioSession = AVAudioSession.sharedInstance()
    var playerTimer: Timer?
    var playLocalId: Int = 0
    var playCell: MYGChatVoiceCell?
    var firePlayCell: MYGChatFireCell?
    private var voicePath: String?
    private var withdrawIndex: Int?
    var unreadMessagesNumber: Int = 0
    private var page = 1
    private var userMobile = ""
    // MARK: - init
    init(sessionId: Int,mobile: String = "",mo_shenggx:Int = 0,title:String) {
        self.sessionId = sessionId
        self.mobile = mobile
        self.mo_shenggx = mo_shenggx
        super.init(nibName: nil, bundle: nil)
        self.title = title
    }
    
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    // MARK: - life cycle
    override func viewDidLoad() {
        super.viewDidLoad()
        
        configUI()
        
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(_:)), name: UIResponder.keyboardWillShowNotification, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(_:)), name: UIResponder.keyboardWillHideNotification, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(getMessage), name: NSNotification.Name.init("MYGIMMessageDetail"), object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(getNewMessage), name: NSNotification.Name.init("MYGIMMessageDetailNew"), object: sessionId)
        NotificationCenter.default.addObserver(self, selector: #selector(readMessage), name: NSNotification.Name.init("MYGIMMessageRead"), object: sessionId)
        NotificationCenter.default.addObserver(self, selector: #selector(withDrawMessage), name: NSNotification.Name.init("MYGIMMessageDraw"), object: sessionId)
        NotificationCenter.default.addObserver(self, selector: #selector(templateAdd), name: NSNotification.Name.init("MYGIMMessageTemplate"), object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(readApplyMesage), name: NSNotification.Name.init("MYGIMMessageReadApply"), object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(getMessageSessionId), name: NSNotification.Name.init("MYGIMMessageSession"), object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(showMessage), name: NSNotification.Name.init("MYGIMShowMessage"), object: nil)

        if !self.mobile.isEmpty {
            socket.createDcotorChat(mobile: mobile)
        }else {
            socket.getSingleChatMessage(sessionId)
        }
        
        getEmoji()
        if unreadMessagesNumber > 0 {
            MYGSocketManager.shared.getMessageList()
        }
        
        
        AVCaptureDevice.requestAccess(for: .audio) { granted in
            
        }
        
        let rightBar = UIBarButtonItem(image: UIImage.init(named: "Chat/lahei"), style: .plain, target: self, action: #selector(clickAddBtn))
        rightBar.tintColor = .black
        self.navigationItem.rightBarButtonItem = rightBar
    }
    
    @objc func clickAddBtn(){
        MMYGHUD.showToast(text: "已拉黑对方")
    }
    
    deinit {
        tableView.removeObserver(self, forKeyPath: "contentSize")
        NotificationCenter.default.removeObserver(self)
    }
    @objc func showMessage(_ not: Notification){
        guard let userInfo = not.userInfo as? [String: Any] , let model = MYGUserTipInfoChatModel.deserialize(from: userInfo) else {
            return
        }
        mo_shenggx = 1
        MMYGHUD.showToast(text: model.msg)
        
    }
    
    @objc func getMessageSessionId(_ not: Notification){
        guard let userInfo = not.userInfo as? [String: Any] , let model = MYGIMMessageListSessionModel.deserialize(from: userInfo) else {
            return
        }
        self.sessionId = model.sessionInfo.id
        socket.getSingleChatMessage(sessionId)
        
    }
    @objc
    private func templateAdd(_ not: Notification) {
        guard let userInfo = not.userInfo as? [String: Any], let model = MYGIMFastMessageModel.deserialize(from: userInfo) else {
            return
        }
        
        if userInfo["action"] as? String == "delete" {
            fastMessages.removeAll { item in
                item.id == model.id
            }
            return
        }
        
        
        if fastMessages.contains(where: { item in
            item.id == model.id
        }) {
            let item = fastMessages.first { item in
                item.id == model.id
            }
            item?.message_content = model.message_content
        } else {
            fastMessages.append(model)
        }
    }
    @objc private func readApplyMesage(_ not: Notification){
        //socket.getSingleChatMessage(sessionId)
        guard let userInfo = not.userInfo as? [String: Any], let session = userInfo["messageData"] as? [String: Any], let model = MYGIMReadApplyChatData.deserialize(from: session) else {
            return
        }
        for (index, value) in contents.enumerated() {
            if let item = value as? MYGChatReportCellModel,item.localhostId == model.localhost_id  {
                    item.is_agree = model.is_agree
                    tableView.reloadRows(at: [IndexPath(row: index, section: 0)], with: .automatic)
                    break
            }
        }

    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        IQKeyboardManager.shared.enable = false
//        IQKeyboardManager.shared.enableAutoToolbar = false
        startOnceLocation()
    }
    override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)
        IQKeyboardManager.shared.enable = true
    }
        
    // MARK: - 配置cell
    private func configItem() {
        print("Current:\(Thread.current)")
        contents = []
        
        for item in chatHistorys {
            let model = dealModel(item)
            contents.append(model)
        }
    }
   
    // MARK: - UI
    private func configUI() {
//        self.title = "消息"
        view.backgroundColor = .white
//        view.addSubview(stackView)
        view.addSubview(backButton)
        //stackView.addArrangedSubviews([tableView, enterView, collectionView, emojiCollectionView, footerView])
        view.addSubview(tableView)
        view.addSubview(enterView)
        view.addSubview(collectionView)
        view.addSubview(emojiCollectionView)
        view.addSubview(footerView)
        view.addSubview(srcollView)
        srcollView.snp.makeConstraints { make in
            make.top.left.equalToSuperview()
            make.width.equalTo(screenWidth)
            
        }
        
        tableView.snp.makeConstraints { make in
            make.top.left.right.equalToSuperview()
            make.height.equalTo(screenHeight - navHeight - statusBarHeight - bottomSafeheight - 41)
        }
        
        enterView.snp.makeConstraints { make in
            make.top.equalTo(tableView.snp.bottom)
//            make.bottom.equalToSuperview()
            make.width.equalTo(screenWidth)
            make.height.equalTo(41)
        }
        
        collectionView.snp.makeConstraints { make in
            make.top.equalTo(enterView.snp.bottom)
            make.width.equalTo(screenWidth)
            make.height.equalTo(97 + bottomSafeheight)
        }
        
        emojiCollectionView.snp.makeConstraints { make in
            make.top.equalTo(enterView.snp.bottom)
            make.width.equalTo(screenWidth)
            make.height.equalTo((screenWidth/2))
        }
        
        footerView.snp.makeConstraints { make in
            make.top.equalTo(enterView.snp.bottom)
            make.width.equalTo(screenWidth)
            make.height.equalTo(bottomSafeheight)
        }
        
//        stackView.snp.makeConstraints { make in
//            make.edges.equalToSuperview()
//        }
    }
    
    // MARK: - lazy load
    private lazy var srcollView:UIScrollView = {
        let src = UIScrollView()
        return src
    }()
    
    private lazy var tableView: UITableView = {
        let tableV = UITableView()
        tableV.separatorStyle = .none
        tableV.register(cellWithClass: MYGChatContentCell.self)// 文本
        tableV.register(cellWithClass: MYGChatPhotoCell.self)//图片
        tableV.register(cellWithClass: MYGChatPositionCell.self)//位置
        tableV.register(cellWithClass: MYGChatFireCell.self)//阅后
        tableV.register(cellWithClass: MYGChatVoiceCell.self)//声音
        tableV.register(cellWithClass: MYGWithdrawCell.self)// 撤回
        tableV.register(cellWithClass: MYGReportCell.self)// 查看报告
        tableV.delegate = self
        tableV.dataSource = self
        
        let header = MJRefreshNormalHeader {[weak self] in
            guard let self = self else {
                return
            }
            page+=1
            socket.getSingleChatMessage(sessionId, page: page)
        }
        header.setTitle("下拉加载更多数据", for: .willRefresh)
        header.setTitle("加载中", for: .pulling)
        tableV.mj_header = header
        
        tableV.addObserver(self, forKeyPath: "contentSize", options: .new, context: nil)
        return tableV
    }()
    
    private lazy var stackView: UIStackView = {
        let stackV = UIStackView()
        stackV.axis = .vertical
        return stackV
    }()
    
    private lazy var enterView: MYGChatEnterView = {
        let view = MYGChatEnterView()
        view.textField.delegate = self
        view.emojiAction = {[weak self] in
            guard let self = self else {
                return
            }
            
            self.collectionView.isHidden = true
            self.emojiCollectionView.isHidden = !self.emojiCollectionView.isHidden
            tableView.snp.remakeConstraints { make in
                make.top.right.left.equalToSuperview()
                if(self.emojiCollectionView.isHidden) {
                    make.height.equalTo(screenHeight - navHeight - statusBarHeight - bottomSafeheight - 41)
                }else {
                    make.height.equalTo(screenHeight - navHeight - statusBarHeight - (screenWidth/2)  - 41)
                }
            }
        }
        
        view.addAction = {[weak self] in
            guard let self = self else {
                return
            }
            
            self.collectionView.isHidden = !self.collectionView.isHidden
            self.emojiCollectionView.isHidden = true
            tableView.snp.remakeConstraints { make in
                make.top.right.left.equalToSuperview()
                if(self.collectionView.isHidden) {
                    make.height.equalTo(screenHeight - navHeight - statusBarHeight - bottomSafeheight - 41)
                }else {
                    make.height.equalTo(screenHeight - navHeight - statusBarHeight - 97  - 41)
                }
            }
        }
        
        view.recoardAction = {[weak self] isRecord in
            if isRecord {
                self?.record()
            } else {
                self?.stopRecord()
            }
        }
        return view
    }()
    
    private lazy var collectionView: UICollectionView = {
        let layout = UICollectionViewFlowLayout()
        layout.scrollDirection = .horizontal
        layout.itemSize = CGSize(width: 78, height: 97)
        layout.minimumLineSpacing = 0
        layout.minimumInteritemSpacing = 0
        layout.sectionInset = .init(top: 0, left: 18, bottom: 0, right: 18)
        
        let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
        cv.delegate = self
        cv.dataSource = self
        cv.register(cellWithClass: MYGChatFunctionCell.self)
        cv.showsHorizontalScrollIndicator = false
        cv.isHidden = true
        return cv
    }()
    
    private lazy var emojiCollectionView: UICollectionView = {
        let layout = UICollectionViewFlowLayout()
        layout.scrollDirection = .vertical
        layout.itemSize = CGSize(width: (screenWidth/10), height: (screenWidth/10))
        layout.minimumLineSpacing = 0
        layout.minimumInteritemSpacing = 0
        
        let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
        cv.delegate = self
        cv.dataSource = self
        cv.register(cellWithClass: MYGEmojiCell.self)
        cv.showsHorizontalScrollIndicator = false
        cv.isHidden = true
        return cv
    }()
    
    private lazy var footerView: UIView = {
        let view = UIView()
        view.backgroundColor = .white
        return view
    }()
    
    private lazy var locationManager: BMKLocationManager = {
        let manager = BMKLocationManager()
        manager.delegate = self
        manager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
        return manager
    }()
    
    private lazy var backButton: QMUIButton = {
        let btn = QMUIButton()
        btn.setTitle("撤回", for: .normal)
        btn.setTitleColor(.white, for: .normal)
        btn.titleLabel?.font = .regular(11)
        btn.setImage(UIImage(named: "Chat/withdraw"), for: .normal)
        btn.setBackgroundImage(UIImage(named: "Chat/withdraw_bg"), for: .normal)
        btn.imagePosition = .left
        btn.spacingBetweenImageAndTitle = 4
        btn.isHidden = true
        btn.contentEdgeInsets = .init(top: 2, left: 0, bottom: 0, right: 0)
        btn.contentVerticalAlignment = .top
        
        btn.addTarget(self, action: #selector(drawMessage), for: .touchUpInside)
        return btn
    }()
}

extension MYGChatController: UITableViewDelegate, UITableViewDataSource {
    func numberOfSections(in tableView: UITableView) -> Int {
        1
    }
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        contents.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let item = contents[indexPath.row]
        if let item = item as? MYGChatContentCellModel {
            let cell = tableView.dequeueReusableCell(withClass: MYGChatContentCell.self, for: indexPath)
            cell.model = item
            cell.reloadAction = {[weak self] in
                self?.reloadIndex(indexPath)
            }
            
            cell.withdrawAction = {[weak self, weak cell] in
                guard let self = self, let cell = cell else {
                    return
                }
                
                if item.isLeft {
                    return
                }
                
                self.backButton.isHidden = false
                self.backButton.snp.remakeConstraints { make in
                    make.top.equalTo(cell.snp.top).offset(25)
                    make.centerX.equalTo(cell.bgView)
                    make.width.equalTo(50)
                    make.height.equalTo(22)
                }
                
                self.withdrawIndex = indexPath.row
            }
            cell.tapActionBlock = { [weak self] in
                guard let self = self else {
                    return
                }
                
                if item.isLeft {
                    if item.attribute != nil {
                         let vc = MYGPDFViewController()
                        let originalString = item.content
//                        let startIndex = originalString.index(originalString.startIndex, offsetBy: 3)
//                        let urlString = originalString[startIndex...]
                        vc.pdfUrl = originalString
                        self.navigationController?.pushViewController(vc)
                    }
                    
                    return
                }
            }
            
            return cell
        }
        
        if let item = item as? MYGChatImageCellModel {
            let cell = tableView.dequeueReusableCell(withClass: MYGChatPhotoCell.self, for: indexPath)
            cell.model = item
            cell.reloadAction = {[weak self] in
                self?.reloadIndex(indexPath)
            }
            cell.withdrawAction = {[weak self, weak cell] in
                guard let self = self, let cell = cell else {
                    return
                }
                if item.isLeft {
                    return
                }
                self.backButton.isHidden = false
                self.backButton.snp.remakeConstraints { make in
                    make.top.equalTo(cell.snp.top).offset(25)
                    make.centerX.equalTo(cell.contentImageView)
                    make.width.equalTo(50)
                    make.height.equalTo(22)
                }
                
                self.withdrawIndex = indexPath.row
            }
            cell.showbigImageView = { [weak self, weak cell] in
                let vc = QMUIImagePreviewViewController()
                vc.imagePreviewView.delegate = self
                vc.imagePreviewView.currentImageIndex = UInt(indexPath.row)
                vc.sourceImageView = {
                    return cell?.contentImageView
                }
                vc.presentingStyle = .zoom
                vc.dismissingStyle = .fade
                UIViewController.currentViewController?.present(vc, animated: true)
            }
            return cell
        }
        
        if let item = item as? MYGChatPositionModel {
            let cell = tableView.dequeueReusableCell(withClass: MYGChatPositionCell.self, for: indexPath)
            cell.model = item
            cell.withdrawAction = {[weak self, weak cell] in
                guard let self = self, let cell = cell else {
                    return
                }
                if item.isLeft {
                    return
                }
                self.backButton.isHidden = false
                self.backButton.snp.remakeConstraints { make in
                    make.top.equalTo(cell.snp.top).offset(25)
                    make.centerX.equalTo(cell.mainView)
                    make.width.equalTo(50)
                    make.height.equalTo(22)
                }
                
                self.withdrawIndex = indexPath.row
            }
            return cell
        }
        
        if let item = item as? MYGChatFireCellModel {
            let cell = tableView.dequeueReusableCell(withClass: MYGChatFireCell.self, for: indexPath)
            cell.model = item
            cell.playAction = {[weak self] item in
                if let player = self?.player, player.isPlaying {
                    self?.stopPlay()
                }
                
                self?.firePlayCell = cell
                
                if let url = item.localPath {
                    self?.playRecord(url, isNetwork: false)
                } else {
                    self?.playRecord(item.webPath, isNetwork: true)
                }
            }
            
            cell.cancelPlayAction = {[weak self] in
                self?.stopPlay()
            }
            return cell
        }
        
        if let item = item as? MYGChatVoiceCellModel {
            let cell = tableView.dequeueReusableCell(withClass: MYGChatVoiceCell.self, for: indexPath)
            cell.model = item
            
            cell.playAction = {[weak self] in
                if let player = self?.player, player.isPlaying {
                    self?.stopPlay()
                    if item.localId == self?.playLocalId {
                        return
                    }
                }
                
                self?.playLocalId = item.localId
                self?.playCell = cell
                
                if let url = item.localPath {
                    self?.playRecord(url, isNetwork: false)
                } else {
                    self?.playRecord(item.webPath, isNetwork: true)
                }
            }
            
            cell.withdrawAction = {[weak self, weak cell] in
                guard let self = self, let cell = cell else {
                    return
                }
                if item.isLeft {
                    return
                }
                self.backButton.isHidden = false
                self.backButton.snp.remakeConstraints { make in
                    make.top.equalTo(cell.snp.top).offset(25)
                    make.centerX.equalTo(cell.mainView)
                    make.width.equalTo(50)
                    make.height.equalTo(22)
                }
                
                self.withdrawIndex = indexPath.row
            }
            
            return cell
        }
        
        if let item = item as? MYGChatWithdrawCellModel {
            let cell = tableView.dequeueReusableCell(withClass: MYGWithdrawCell.self, for: indexPath)
            cell.model = item
            cell.withDrawAction = {[weak self] text in
                self?.enterView.textField.text = text
            }
            return cell
        }
        // MARK: - 报告
        if let item = item as? MYGChatReportCellModel {
            let cell = tableView.dequeueReusableCell(withClass: MYGReportCell.self, for: indexPath)
            cell.model = item
            cell.withDrawAction = {[weak self] type in
                self!.apply(with:type)
            }
            return cell
        }
        
        
        return UITableViewCell()
    }
    
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        backButton.isHidden = true
    }
    
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        backButton.isHidden = true
    }
}

extension MYGChatController: UICollectionViewDelegateFlowLayout, UICollectionViewDataSource {
    func numberOfSections(in collectionView: UICollectionView) -> Int {
        1
    }
    
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        if collectionView == emojiCollectionView {
            return emoji.emoji.count
        }
        return functions.count
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        if collectionView == emojiCollectionView {
            let cell = collectionView.dequeueReusableCell(withClass: MYGEmojiCell.self, for: indexPath)
            cell.model = emoji.emoji[indexPath.row]
            return cell
        }
        
        let cell = collectionView.dequeueReusableCell(withClass: MYGChatFunctionCell.self, for: indexPath)
        cell.type = functions[indexPath.row]
        return cell
    }
    
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        if collectionView == emojiCollectionView {
            let emoji = emoji.emoji[indexPath.row]
            
            var text = enterView.textField.text ?? ""
            text = "\(text)\(emoji.code)"
            enterView.textField.text = text
            return
        }
        
        
        let type = functions[indexPath.row]
        
        switch type {
        case .image:
            selectPhoto()
        case .photo:
            selectCamera()
        case .position:
            selectPosition()
        case .message:
            selectTemplate()
        case .report:
            selectReport()
        case .appoint:
            selectLimit()
        }
    }
    
    func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
        if scrollView == tableView {
            needScroll = false
        }
    }
}

extension MYGChatController: UITextFieldDelegate {
    // MARK: - 处理调整健康数据 apply1=健康数据申请,apply2=生活习惯申请,apply3=健康史申请,apply4=病历夹申请,apply5=体检报告申请
    func apply(with type: MYGIMMessageType) {
        
        let phone = userMobile
        //TODO: 把手机号换成从接口取
        MYGLoading.show()
        MYGNetwork<MYGHomePageAPI, MYGChatDoctorApplicationModel>.request(target: .doctorApplicationInfo(patientPhone: phone, reportId: String(type.applyIndex))) { result in
            MYGLoading.hide()
            self.goToVC(type: type, patient: result.patient)
        } failed: { _, error in
            MYGLoading.hide()
            MMYGHUD.showToast(text: error)
        }
    }
    
    func goToVC(type: MYGIMMessageType, patient: MYGPatientModel?) {
        guard let patient = patient else {
            MMYGHUD.showToast(text: "没有查询到患者信息")
            return
        }
        
        var str = ""
        switch type {
        case .apply1:
            str = "健康数据"
            let vc = MYGHealthManagementViewController()
            vc.patientId = patient.id
            vc.name = patient.name
            vc.headUrl = patient.avatar
            vc.type = .statistics
            self.navigationController?.pushViewController(vc)
        case .apply2:
            str = "生活习惯"
            let vc = MYGHealthManagementViewController()
            vc.patientId = patient.id
            vc.name = patient.name
            vc.headUrl = patient.avatar
            vc.type = .habit
            self.navigationController?.pushViewController(vc)
        case .apply3:
            str = "健康史"
            let vc = MYGHealthManagementViewController()
            vc.patientId = patient.id
            vc.name = patient.name
            vc.headUrl = patient.avatar
            vc.type = .history
            self.navigationController?.pushViewController(vc)
        case .apply4:
            str = "病历夹"
            let vc = MYGCaseFilesDetailViewController()
            self.navigationController?.pushViewController(vc)
        case .apply5,.card:
            str = "体检报告"
            let vc = MYGPDFViewController()
            vc.pdfUrl = ""
            self.navigationController?.pushViewController(vc)
        default:
            str = "健康数据"
        }
    }
    
    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        guard let text = textField.text, !text.isEmpty else { return false }
        textField.text = ""
        sendMessage(text)
        //textField.resignFirstResponder()
    
        return true
    }
    
    private func sendMessage(_ str: String) {
        // 陌生消息 1. 如果陌生进入页面，说明有一天消息  就只能发送一条 2， 如果好友、可能认识的人进入 可以发一条
        if  contents.count == 1 && !self.mobile.isEmpty || ( contents.count == 1 && mo_shenggx == 1)  {
            let item = contents.first
            if ((item as? MYGChatContentCellModel) != nil) {
                let model: MYGChatContentCellModel  = (contents.first as! MYGChatContentCellModel)
                if model.isLeft == false {
                    MMYGHUD.showToast(text: "未成为好友，对方回复您之前，只能发送一条消息")
                    return
                }
            }else if ((item as? MYGChatImageCellModel) != nil) {
                let model: MYGChatImageCellModel  = (contents.first as! MYGChatImageCellModel)
                if model.isLeft == false {
                    MMYGHUD.showToast(text: "未成为好友，对方回复您之前，只能发送一条消息")
                    return
                }
            }else if ((item as? MYGChatPositionModel) != nil) {
                let model: MYGChatPositionModel  = (contents.first as! MYGChatPositionModel)
                if model.isLeft == false {
                    MMYGHUD.showToast(text: "未成为好友，对方回复您之前，只能发送一条消息")
                    return
                }
            }else if ((item as? MYGChatVoiceCellModel) != nil) {
                let model: MYGChatVoiceCellModel  = (contents.first as! MYGChatVoiceCellModel)
                if model.isLeft == false {
                    MMYGHUD.showToast(text: "未成为好友，对方回复您之前，只能发送一条消息")
                    return
                }
            }
            
        }
        
        if contents.count == 2{
            if self.mobile.isEmpty && mo_shenggx == 1 {
                MMYGHUD.showToast(text: "未成为好友，对方回复您之前，只能发送一条消息")
                return
            }
        }
       
       
        needScroll = true
        let text = replaceEmoji(str)
        let time = Int(Date().timeIntervalSince1970)
        socket.sendTextMessage(text, sessionId: sessionId, is_destruction: enterView.isFire ? 1 : 0, date: time)

        let model = MYGChatContentCellModel(avatar: socket.user?.avatar ?? "", name: socket.user?.nickname ?? "", content: text)
        model.isFire = enterView.isFire
        model.localhostId = time
        if enterView.isFire {
            let item = MYGChatFireCellModel()
            item.avatar = model.avatar
            item.name = model.name
            item.isLeft = model.isLeft
            item.model = model
            item.localhostId = time
            contents.append(item)
        } else {
            contents.append(model)
        }
        
        
        tableView.beginUpdates()
        tableView.insertRows(at: [IndexPath(row: contents.count-1, section: 0)], with: .bottom)
        tableView.endUpdates()
    }
    
    private func sendReportMessage(_ text: String,type: MYGIMMessageType) {
        needScroll = true
        let time = Int(Date().timeIntervalSince1970)
        self.socket.sendReportMessage(text, type: type,sessionId: self.sessionId, is_destruction:  enterView.isFire ? 1 : 0, date: time)
        
        let name:String = MYGUserManager.getUser()!.username
        let avatar:String = "https://img0.baidu.com/it/u=16091393,4116349968&fm=253&app=138&size=w931&n=0&f=JPEG&fmt=auto?sec=1709398800&t=fa2247ad227524e59de4aec3244e6d2e"
//        let model = MYGChatContentCellModel(avatar:avatar, name: name, content: text)
        let model = MYGChatReportCellModel(type: type, avatar: avatar, name: name, content: text)
        let localhostId = Int("\(time)\(type.applyIndex)")
        model.localhostId = localhostId!
        contents.append(model)
        
        tableView.beginUpdates()
        tableView.insertRows(at: [IndexPath(row: contents.count-1, section: 0)], with: .bottom)
        tableView.endUpdates()
    }
    

    private func sendImage(_ image: UIImage) {
   
        if  contents.count == 1 && !self.mobile.isEmpty || ( contents.count == 1 && mo_shenggx == 1)  {
            let item = contents.first
            if ((item as? MYGChatContentCellModel) != nil) {
                let model: MYGChatContentCellModel  = (contents.first as! MYGChatContentCellModel)
                if model.isLeft == false {
                    MMYGHUD.showToast(text: "未成为好友，对方回复您之前，只能发送一条消息")
                    return
                }
            }else if ((item as? MYGChatImageCellModel) != nil) {
                let model: MYGChatImageCellModel  = (contents.first as! MYGChatImageCellModel)
                if model.isLeft == false {
                    MMYGHUD.showToast(text: "未成为好友，对方回复您之前，只能发送一条消息")
                    return
                }
            }else if ((item as? MYGChatPositionModel) != nil) {
                let model: MYGChatPositionModel  = (contents.first as! MYGChatPositionModel)
                if model.isLeft == false {
                    MMYGHUD.showToast(text: "未成为好友，对方回复您之前，只能发送一条消息")
                    return
                }
            }else if ((item as? MYGChatVoiceCellModel) != nil) {
                let model: MYGChatVoiceCellModel  = (contents.first as! MYGChatVoiceCellModel)
                if model.isLeft == false {
                    MMYGHUD.showToast(text: "未成为好友，对方回复您之前，只能发送一条消息")
                    return
                }
            }
            
        }
        
        if contents.count == 2{
            if self.mobile.isEmpty && mo_shenggx == 1 {
                MMYGHUD.showToast(text: "未成为好友，对方回复您之前，只能发送一条消息")
                return
            }
        }
        
        needScroll = true
        let time = Int(Date().timeIntervalSince1970)

        let model = MYGChatImageCellModel()
        model.avatar = socket.user?.avatar ?? ""//avatar
        model.name = socket.user?.nickname ?? ""
        model.localImage = image
        model.isFire = enterView.isFire
        model.localhostId = time
        if enterView.isFire {
            let item = MYGChatFireCellModel()
            item.avatar = model.avatar
            item.name = model.name
            item.isLeft = model.isLeft
            item.model = model
            item.localhostId = time
            contents.append(item)
        } else {
            contents.append(model)
        }
        let index = IndexPath(row: contents.count-1, section: 0)
        tableView.beginUpdates()
        tableView.insertRows(at: [index], with: .bottom)
        tableView.endUpdates()
        
        MYGLoading.show(self.view)
        MYGNetwork<MYGSocketAPI, MYGUploadFileModel>.request(target: .uploadFile(image: image)) { result in
            MYGLoading.hide(self.view)
//            guard let result = result else {
//                return
//            }
            
            self.socket.sendImageMessage(result.fullurl, sessionId: self.sessionId, is_destruction: self.enterView.isFire ? 1 : 0, date: time)
        } failed: { _, error in
            MYGLoading.hide(self.view)
            MMYGHUD.showToast(text: error)
        }
    }
    
    private func sendPosition(_ model: MYGMapPositionModel) {
        
        if  contents.count == 1 && !self.mobile.isEmpty || ( contents.count == 1 && mo_shenggx == 1)  {
            let item = contents.first
            if ((item as? MYGChatContentCellModel) != nil) {
                let model: MYGChatContentCellModel  = (contents.first as! MYGChatContentCellModel)
                if model.isLeft == false {
                    MMYGHUD.showToast(text: "未成为好友，对方回复您之前，只能发送一条消息")
                    return
                }
            }else if ((item as? MYGChatImageCellModel) != nil) {
                let model: MYGChatImageCellModel  = (contents.first as! MYGChatImageCellModel)
                if model.isLeft == false {
                    MMYGHUD.showToast(text: "未成为好友，对方回复您之前，只能发送一条消息")
                    return
                }
            }else if ((item as? MYGChatPositionModel) != nil) {
                let model: MYGChatPositionModel  = (contents.first as! MYGChatPositionModel)
                if model.isLeft == false {
                    MMYGHUD.showToast(text: "未成为好友，对方回复您之前，只能发送一条消息")
                    return
                }
            }else if ((item as? MYGChatVoiceCellModel) != nil) {
                let model: MYGChatVoiceCellModel  = (contents.first as! MYGChatVoiceCellModel)
                if model.isLeft == false {
                    MMYGHUD.showToast(text: "未成为好友，对方回复您之前，只能发送一条消息")
                    return
                }
            }
            
        }
        
        if contents.count == 2{
            if self.mobile.isEmpty && mo_shenggx == 1 {
                MMYGHUD.showToast(text: "未成为好友，对方回复您之前，只能发送一条消息")
                return
            }
        }
        
        let time = Int(Date().timeIntervalSince1970)
        let item = MYGChatPositionModel()
        item.avatar = socket.user?.avatar ?? "" //avatar
        item.name = userName
        item.posisitonName = model.name
        item.coor = model.model.pt
        item.localhostId = time
        var distanseText = ""
        if let coordinate = coordinate {
            let point1 = coordinate
            let point2 = model.model.pt
            let distance = Int(BMKMetersBetweenCoordinates(point1, point2))
            if distance <= 100 {
                distanseText = "100m内"
            } else if distance > 100 && distance < 1000 {
                distanseText = "\(distance)m"
            } else {
                distanseText = String(format: "%.2fkm", CGFloat(distance)/1000)
            }
        }
        
        item.hint = "\(distanseText) | \(model.model.address ?? "")"

        item.imageUrl = "https://api.map.baidu.com/staticimage/v2?ak=\(mapJSAK)&mcode=\(mapJSAK)&center=\(model.model.pt.longitude),\(model.model.pt.latitude)&width=228&height=103&zoom=15&markers=\(model.model.pt.longitude),\(model.model.pt.latitude)&markerStyles=-1,https://api.map.baidu.com/images/marker_red.png,-1,23,25"
        contents.append(item)
        
        let index = IndexPath(row: contents.count-1, section: 0)
        tableView.beginUpdates()
        tableView.insertRows(at: [index], with: .bottom)
        tableView.endUpdates()
        
        let sendModel = MYGIMMessageSendPositionModelPosition()
        sendModel.addressName = model.model.name
        sendModel.streetName = model.model.address
        sendModel.longitude = model.model.pt.longitude
        sendModel.latitude = model.model.pt.latitude
        socket.sendPositionMessage(sendModel, sessionId: sessionId, date: time)
    }
    
    private func sendVoice(_ url: String, duration: Int) {
        if  contents.count == 1 && !self.mobile.isEmpty || ( contents.count == 1 && mo_shenggx == 1)  {
            let item = contents.first
            if ((item as? MYGChatContentCellModel) != nil) {
                let model: MYGChatContentCellModel  = (contents.first as! MYGChatContentCellModel)
                if model.isLeft == false {
                    MMYGHUD.showToast(text: "未成为好友，对方回复您之前，只能发送一条消息")
                    return
                }
            }else if ((item as? MYGChatImageCellModel) != nil) {
                let model: MYGChatImageCellModel  = (contents.first as! MYGChatImageCellModel)
                if model.isLeft == false {
                    MMYGHUD.showToast(text: "未成为好友，对方回复您之前，只能发送一条消息")
                    return
                }
            }else if ((item as? MYGChatPositionModel) != nil) {
                let model: MYGChatPositionModel  = (contents.first as! MYGChatPositionModel)
                if model.isLeft == false {
                    MMYGHUD.showToast(text: "未成为好友，对方回复您之前，只能发送一条消息")
                    return
                }
            }else if ((item as? MYGChatVoiceCellModel) != nil) {
                let model: MYGChatVoiceCellModel  = (contents.first as! MYGChatVoiceCellModel)
                if model.isLeft == false {
                    MMYGHUD.showToast(text: "未成为好友，对方回复您之前，只能发送一条消息")
                    return
                }
            }
            
        }
        
        if contents.count == 2{
            if self.mobile.isEmpty && mo_shenggx == 1 {
                MMYGHUD.showToast(text: "未成为好友，对方回复您之前，只能发送一条消息")
                return
            }
        }
        
        let time = Int(Date().timeIntervalSince1970)

        let model = MYGChatVoiceCellModel()
        model.avatar = socket.user?.avatar ?? "" //avatar
        model.name = socket.user?.nickname ?? ""
        model.localPath = url
        model.isFire = enterView.isFire
        model.duration = duration
        model.localId = time
        if enterView.isFire {
            let item = MYGChatFireCellModel()
            item.avatar = model.avatar
            item.name = model.name
            item.isLeft = model.isLeft
            item.model = model
            item.localhostId = time
            contents.append(item)
        } else {
            contents.append(model)
        }
        
        let index = IndexPath(row: contents.count-1, section: 0)
        tableView.beginUpdates()
        tableView.insertRows(at: [index], with: .bottom)
        tableView.endUpdates()
        
        let file_path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first?.appending(url)
        let url = URL(fileURLWithPath: file_path!)
        if let data = try? Data(contentsOf: url) {
            MYGLoading.show(self.view)
            MYGNetwork<MYGSocketAPI, MYGUploadFileModel>.request(target: .uploadFile(image: nil, data: data, fileName: "\(time).wav", type: "audio/*")) { result in
                MYGLoading.hide(self.view)
//                guard let result = result else {
//                    return
//                }
                
                self.socket.sendVoiceMessage(result.fullurl, duration: duration, sessionId: self.sessionId, is_destruction: self.enterView.isFire ? 1 : 0, date: time)
            } failed: { _, error in
                MYGLoading.hide(self.view)
                MMYGHUD.showToast(text: error)
            }
        }
    }
    
    private func selectPhoto() {
        let picker = TZImagePickerController(maxImagesCount: 1, delegate: self)!
        picker.maxImagesCount = 1
        picker.allowPickingVideo = false
        picker.allowTakePicture = false
        self.present(picker, animated: true)
    }
    
    private func selectCamera() {
        let picker = UIImagePickerController()
        picker.sourceType = .camera
        picker.mediaTypes = ["public.image"]
        picker.delegate = self
        picker.modalPresentationStyle = .fullScreen
        self.present(picker, animated: true)
    }
    
    private func selectLimit() {
        let vc = MYGHealthMenuController()
        vc.show()
        vc.patient_phone = userMobile
        vc.selAction = {[weak self] item in
            self?.dismiss(animated: true)
            
//            let contents = ["健康数据", "生活习惯", "健康史", "病历夹", "体检报告"]
//            let attribute = NSMutableAttributedString.rz.colorfulConfer { confer in
//                confer.text("陈医生向您申请查看\(contents[index])，")?.font(.regular(12)).textColor(.rgba(51, 51, 51, 1))
//                confer.text("这就去处理")?.font(.regular(12)).textColor(.blue).tapActionByLable("appoint")
//            }!
            
//            let name:String = MYGUserManager.getUser()!.username
//            let content:String =  "\(name)申请查看你的\(item.content)"
//            var params: [String: ()->Void] = [:]
//            params["appoint"] = {
//                
//            }
            self?.sendReportMessage("申请消息已发送", type: item.type)
        }
    }
    
    private func selectTemplate() {
        let vc = MYGChatTemplateController(fastMessages)
        vc.sessionId = sessionId
        vc.sendAction = {[weak self] str in
            self?.sendMessage(str)
        }
        vc.show()
    }
    
    private func selectReport() {
        let vc = MYGChatShareReportController()
        vc.sendAction = {str in
          
        }
        self.navigationController?.pushViewController(vc)
    }
    
    private func selectPosition() {
        let vc = MYGMapMenuController()
        self.navigationController?.pushViewController(vc)
        
        vc.sendAction = {[weak self] item in
            self?.sendPosition(item)
        }
    }
}

extension MYGChatController: TZImagePickerControllerDelegate {
    func imagePickerController(_ picker: TZImagePickerController!, didFinishPickingPhotos photos: [UIImage]!, sourceAssets assets: [Any]!, isSelectOriginalPhoto: Bool, infos: [[AnyHashable : Any]]!) {
        if let image = photos.first {
            sendImage(image)
        }
    }
}

extension MYGChatController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
        picker.dismiss(animated: true)
        if let originalImage = info[UIImagePickerController.InfoKey.originalImage] as? UIImage {
            sendImage(originalImage)
        }
    }
}

extension MYGChatController {
    @objc
    private func keyboardWillShow(_ noti:Notification) {
        if let keyboardSize = (noti.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
                let keyboardHeight = keyboardSize.height
                // 使用键盘的高度进行后续操作
            tableView.snp.remakeConstraints { make in
                make.top.right.left.equalToSuperview()
                make.height.equalTo(screenHeight - navHeight - statusBarHeight - bottomSafeheight - keyboardHeight - 41)
//                make.height.equalTo(screenHeight - 64 - keyboardHeight - bottomSafeheight - 41)
            }
        }
        collectionView.isHidden = true
        footerView.isHidden = true
        emojiCollectionView.isHidden = true
    }
    
    @objc
    private func keyboardWillHide(_ noti:Notification) {
        if let keyboardSize = (noti.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
//                let keyboardHeight = keyboardSize.height
                // 使用键盘的高度进行后续操作
            tableView.snp.remakeConstraints { make in
                make.top.right.left.equalToSuperview()
//                make.height.equalTo(screenHeight - 64 - 41)
                make.height.equalTo(screenHeight - navHeight - statusBarHeight - bottomSafeheight - 41)
            }
        }
        footerView.isHidden = false
    }
}

extension MYGChatController {
    @objc
    private func getMessage(_ not: Notification) {
        tableView.mj_header?.endRefreshing()
        guard let userInfo = not.userInfo as? [String: Any], let model = MYGIMSingleChatModel.deserialize(from: userInfo) else {
            return
        }
        
        fastMessages = model.fastmessage
        
        if !model.nextpage {
            tableView.mj_header = nil
        }
        
        if chatHistoryModel.contains(where: { item in
            item.data.page == model.data.page
        }) {
            chatHistoryModel.removeAll { item in
                item.data.page == model.data.page
            }
        }
        
        chatHistoryModel.append(model)
        
        chatHistoryModel = chatHistoryModel.sorted{$0.data.page > $1.data.page}
        avatar = model.info.sessionUser.avatar
        userName = model.info.sessionUser.nickname
        userMobile = model.info.sessionUser.mobile
        configItem()
        
        
        if model.data.page == 1 {
            tableView.reloadData()
        } else {
            var indexs = [IndexPath]()
            
            var count = 0
            for item in model.message {
                count += item.data.count
            }
            tableView.reloadData()
            for i in 0 ..< count {
                let index = IndexPath(row: i, section: 0)
                indexs.append(index)
            }
            
            UIView.performWithoutAnimation {
//                tableView.insertRows(at: indexs, with: .none)
                tableView.reloadData()
            }
            
            
            DispatchQueue.main.async {
                self.tableView.scrollToRow(at: IndexPath(row: count, section: 0), at: .top, animated: false)
            }
        }
        
    }
    
    @objc
    private func getNewMessage(_ not: Notification) {
        guard let userInfo = not.userInfo as? [String: Any], let params = userInfo["messageData"] as? [String: Any], let item = MYGIMSingleChatListData.deserialize(from: params) else {
            return
        }
        
        needScroll = true
        let model = dealModel(item)
        contents.append(model)
        
        let index = IndexPath(row: contents.count-1, section: 0)
        tableView.beginUpdates()
        tableView.insertRows(at: [index], with: .automatic)
        tableView.endUpdates()
        
        DispatchQueue.main.asyncAfter(deadline: .now()+0.2, execute: {
            self.tableView.scrollToRow(at: index, at: UITableView.ScrollPosition.bottom, animated: true)
        })
    }
    
    @objc
    private func readMessage(_ not: Notification) {
        guard let userInfo = not.userInfo as? [String: Any], let localhost_id = Int(userInfo["localhost_id"] as? String ?? ""), localhost_id > 0 else {
            return
        }
        
        for (index, value) in contents.enumerated() {
            if let item = value as? MYGChatFireCellModel, item.localhostId == localhost_id, !item.isLeft {
                item.isRead = true
                tableView.reloadRows(at: [IndexPath(row: index, section: 0)], with: .automatic)
                break
            }
        }
    }
    
    private func dealModel(_ item: MYGIMSingleChatListData) -> Any {
        var isLeft = true
        if let userid = socket.user?.id {
            isLeft = (userid != item.sender_id)
        }
        
        if item.status == 5 {
            let model = MYGChatWithdrawCellModel()
            model.isUsers = !isLeft
            if item.type == .chat {
                model.message = item.content
            }
            return model
        }
        
        
        switch item.type {
        case .image:
            let model = MYGChatImageCellModel()
            model.isLeft = isLeft
            model.avatar = isLeft ? avatar : socket.user?.avatar ?? ""
            model.name = isLeft ? userName : socket.user?.nickname ?? ""
            model.imageUrl = item.content
            model.localhostId = item.localhost_id
            model.messageId = item.id
            if item.is_destruction == 1 {
                let fireModel = MYGChatFireCellModel()
                fireModel.name = model.name
                fireModel.avatar = model.avatar
                fireModel.isLeft = model.isLeft
                fireModel.isRead = item.status == 1
                fireModel.model = model
                fireModel.fireAction = {[weak self] in
                    guard let self = self else {
                        return
                    }
                    socket.fireMessage(sessionId, item.localhost_id)
                    item.status = 1
                }
                return fireModel
            }
            
            return model
        case .location:
            guard let message = item.message as? [String: Any] else {
                fallthrough
            }
            
            let model = MYGChatPositionModel()
            model.isLeft = isLeft
            model.avatar = isLeft ? avatar : socket.user?.avatar ?? ""
            model.name =  isLeft ? userName : socket.user?.nickname ?? ""
            model.posisitonName = message["addressName"] as? String ?? ""
            model.localhostId = item.localhost_id
            model.messageId = item.id
            let point2 = CLLocationCoordinate2D(latitude: Double(message["latitude"] as? String ?? "") ?? 0, longitude: Double(message["longitude"] as? String ?? "") ?? 0)
            var distanseText = ""
            if let coordinate = coordinate {
                let point1 = coordinate
                let distance = Int(BMKMetersBetweenCoordinates(point1, point2))
                if distance <= 100 {
                    distanseText = "100m内"
                } else if distance > 100 && distance < 1000 {
                    distanseText = "\(distance)m"
                } else {
                    distanseText = String(format: "%.2fkm", CGFloat(distance)/1000)
                }
            }
            model.hint = "\(distanseText) | \(message["streetName"] as? String ?? "")"
            model.imageUrl = "https://api.map.baidu.com/staticimage/v2?ak=\(mapJSAK)&mcode=\(mapJSAK)&center=\(point2.longitude),\(point2.latitude)&width=228&height=103&zoom=15&markers=\(point2.longitude),\(point2.latitude)&markerStyles=-1,https://api.map.baidu.com/images/marker_red.png,-1,23,25"
            model.coor = point2
            return model
        case .voice:
            let model = MYGChatVoiceCellModel()
            model.isLeft = isLeft
            model.avatar = isLeft ? avatar : socket.user?.avatar ?? ""
            model.name = isLeft ? userName : socket.user?.nickname ?? ""
            model.localId = item.localhost_id
            model.messageId = item.id
            let value = MYGIMMessageSendVoiceModelURL.deserialize(from: item.message as? [String: Any])
            model.webPath = value?.voiceUrl ?? ""
            model.duration = value?.time ?? 0
            
            if item.is_destruction == 1 {
                let fireModel = MYGChatFireCellModel()
                fireModel.name = model.name
                fireModel.avatar = model.avatar
                fireModel.isLeft = model.isLeft
                fireModel.isRead = item.status == 1
                fireModel.model = model
                fireModel.fireAction = {[weak self] in
                    guard let self = self else {
                        return
                    }
                    socket.fireMessage(sessionId, item.localhost_id)
                    item.status = 1
                }
                return fireModel
            }
            
            return model
        case .card:
            
            let value = MYGIMMessageSendReportModelURL.deserialize(from: item.message as? [String: Any])
            let info = value?.pdfUrl ?? ""
            
            let attribute = NSMutableAttributedString.rz.colorfulConfer { confer in
                confer.text("请点击消息查收我的报告")?.font(.regular(12)).textColor(.rgba(51, 51, 51, 1))
                //confer.text("\(info)")?.font(.regular(12)).textColor(.rgba(255, 9, 9, 1))
                //confer.text("这就去处理")?.font(.regular(12)).textColor(.rgba(255, 9, 9, 1)).tapActionByLable("appoint")
            }!
            let model = MYGChatContentCellModel(isLeft: isLeft, avatar: isLeft ? avatar : socket.user?.avatar ?? "", name: isLeft ? userName : socket.user?.nickname ?? "", content: info ,attribute: attribute)
            model.messageId = item.id
            model.localhostId = item.localhost_id
            if item.is_destruction == 1 {
                let fireModel = MYGChatFireCellModel()
                fireModel.name = model.name
                fireModel.avatar = model.avatar
                fireModel.isLeft = model.isLeft
                fireModel.isRead = item.status == 1
                fireModel.model = model
                fireModel.fireAction = {[weak self] in
                    guard let self = self else {
                        return
                    }
                    socket.fireMessage(sessionId, item.localhost_id)
                    item.status = 1
                }
                return fireModel
            }
            return model

        case .apply1,.apply2,.apply3,.apply4,.apply5:
            let model = MYGChatReportCellModel(type: item.type, avatar: socket.user?.avatar ?? "", name: socket.user?.nickname ?? "", content: item.content)
            model.isUsers = !isLeft
            model.name = userName
            model.time = item.createtime
            model.is_agree = item.is_agree
            model.messageId = item.id
            model.localhostId = item.localhost_id
            if item.type == .chat {
                model.message = item.content
            }
            return model
        default:
            let model = MYGChatContentCellModel(isLeft: isLeft, avatar: isLeft ? avatar : socket.user?.avatar ?? "", name: isLeft ? userName : socket.user?.nickname ?? "", content: item.content)
            model.messageId = item.id
            model.localhostId = item.localhost_id
            if item.is_destruction == 1 {
                let fireModel = MYGChatFireCellModel()
                fireModel.name = model.name
                fireModel.avatar = model.avatar
                fireModel.isLeft = model.isLeft
                fireModel.isRead = item.status == 1
                fireModel.model = model
                fireModel.fireAction = {[weak self] in
                    guard let self = self else {
                        return
                    }
                    socket.fireMessage(sessionId, item.localhost_id)
                    item.status = 1
                }
                return fireModel
            }
            return model
        }
    }
}

extension MYGChatController {
    private func getEmoji() {
        MMYGNetwork<MYGSocketAPI, MYGEmojiModel>.request(target: .emoji) { model in
            guard let model = model else {
                return
            }

            self.emoji = model
        } failed: { _, _ in
            
        }
    }
    
    private func replaceEmoji(_ text: String) -> String {
        let result = Guitar(pattern: "\\[/[a-zA-Z0-9\\u4e00-\\u9fa5]+\\]").evaluateForStrings(from: text)
        var str = text
        for item in result {
            if emoji.emoji.contains(where: { model in
                model.code == item
            }) {
                let emoji = emoji.emoji.first { model in
                    model.code == item
                }!
                let img = "<img draggable=\"false\" class=\"emoji\" title=\"\(emoji.name)\" src=\"\(emoji.image)\" />"
                str = str.replacingOccurrences(of: item, with: img)
            }
        }
        
        return str
    }
    
    private func reloadIndex(_ indexPath: IndexPath) {
        tableView.reloadRows(at: [indexPath], with: .none)
    }
    
    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        if let keyPath = keyPath, keyPath == "contentSize", needScroll {
            tableView.scrollToBottom(animated: false)
        }
    }
}

extension MYGChatController: BMKLocationManagerDelegate {
    private func startOnceLocation() {
        locationManager.requestLocation(withReGeocode: false, withNetworkState: true) {[weak self] location, state, error in
            if let error = error {
                print("定位失败：\(error)")
                return
            }
            
            if let location = location {
                if let coor = location.location?.coordinate {
                    self?.coordinate = coor
                }
            }
        }
    }
}

extension MYGChatController: AVAudioRecorderDelegate {
    private func record() {
        if let player = player, player.isPlaying {
            player.stop()
            self.player = nil
        }
        
        let path = "/\(sessionId)/\(Int(Date().timeIntervalSince1970)).wav"
        let file_path = (NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first! as NSString).appendingPathComponent(path)
        
        let docPath = (NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first! as NSString).appendingPathComponent("/\(sessionId)")
        do {
            try FileManager.default.createDirectory(at: URL(fileURLWithPath: docPath), withIntermediateDirectories: true)
        } catch {
            print("文件夹创建失败:\(error.localizedDescription)")
        }
        
        do {
            try session.setCategory(.playAndRecord)
        } catch {
            print("播放器类型失败\(error.localizedDescription)")
        }
        
        do {
            try session.setActive(true)
        } catch {
            print("初始化动作失败:\(error.localizedDescription)")
        }
        
        let recordSetting: [String: Any] = [
            AVSampleRateKey: NSNumber(value: 8000),
            AVFormatIDKey: NSNumber(value: kAudioFormatLinearPCM),
            AVLinearPCMBitDepthKey: NSNumber(value: 8),
            AVNumberOfChannelsKey: NSNumber(value: 1),
            AVLinearPCMIsFloatKey: NSNumber(value: true)
        ]
        
        do {
            self.voicePath = path
            let url = URL(fileURLWithPath: file_path)
            recorder = try AVAudioRecorder(url: url, settings: recordSetting)
            recorder?.delegate = self
            recorder?.prepareToRecord()
            recorder?.record()
            
            MMYGHUD.showTimeToast(text: "录音中", duration: TimeInterval(Int.max))
        } catch {
            print("录音失败：\(error.localizedDescription)")
        }
    }
    
    private func stopRecord() {
        if let recorder = recorder {
            if recorder.isRecording {
                
            }
            
            recorder.stop()
            self.recorder = nil
        }
    }
    
    private func playRecord(_ url: String, isNetwork: Bool) {
        if session.category != AVAudioSession.Category.playback {
            do {
                try session.setCategory(AVAudioSession.Category.playback)
            } catch {
                print("播放模式切换失败：\(error.localizedDescription)")
            }
        }
        
        if isNetwork {
            do {
                guard let data = try? Data(contentsOf: URL(string: url)!) else {
                    return
                }
                
                player = try AVAudioPlayer(data: data)
                player?.delegate = self
                player?.prepareToPlay()
                player?.play()
                
                let timer = Timer.init(timeInterval: 1, repeats: true) {[weak self] timer in
                    guard let self = self else {
                        return
                    }
                    if let time = self.player?.currentTime {
                        self.playCell?.timeChange(false, time: Int(time))
                    }
                    
                }
                
                RunLoop.current.add(timer, forMode: .common)
                self.playerTimer = timer
            } catch {
                print("播放失败:\(error.localizedDescription)")
            }
            return
        }
        
        do {
            let file_path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first?.appending(url ?? "")

            player = try AVAudioPlayer(contentsOf: URL(fileURLWithPath: file_path!))
            player?.delegate = self
            player?.prepareToPlay()
            player?.play()
            
            let timer = Timer.init(timeInterval: 1, repeats: true) {[weak self] timer in
                guard let self = self else {
                    return
                }
                if let time = self.player?.currentTime {
                    self.playCell?.timeChange(false, time: Int(time))
                }
                
            }
            
            RunLoop.current.add(timer, forMode: .common)
            self.playerTimer = timer
        } catch {
            print("播放失败:\(error.localizedDescription)")
        }
    }
    
    private func stopPlay() {
        self.player?.stop()
        self.playerTimer?.invalidate()
        self.player = nil
        self.playerTimer = nil

        self.playCell?.timeChange(true, time: 0)
        if let model = firePlayCell?.model {
            if model.isLeft {
                firePlayCell?.fireButton.isSelected = true
                model.isRead = true
                model.fireAction?()
            }
        }
        
        firePlayCell = nil
    }
    
    func audioRecorderDidFinishRecording(_ recorder: AVAudioRecorder, successfully flag: Bool) {
        MMYGHUD.hidToast()

        let file_path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first?.appending(voicePath ?? "")
        
        let asset = AVURLAsset(url: URL(fileURLWithPath: file_path!))
        var duration: Double = 0
        let audioDuration = asset.duration
        duration = CMTimeGetSeconds(audioDuration)
        
        if duration < 1 {
            recorder.deleteRecording()
        } else {
            sendVoice(voicePath ?? "", duration: Int(duration))
        }
    }
}

extension MYGChatController: AVAudioPlayerDelegate {
    func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
        self.playerTimer?.invalidate()
        self.playerTimer = nil
        self.player = nil
        self.playCell?.timeChange(true, time: 0)
        self.playCell = nil
        
        if let model = firePlayCell?.model {
            if model.isLeft {
                firePlayCell?.fireButton.isSelected = true
                model.isRead = true
                model.fireAction?()
            }
        }
        
        firePlayCell = nil
    }
    
    @objc
    private func drawMessage() {
        guard let withdrawIndex = withdrawIndex else {
            return
        }
        
        backButton.isHidden = true
        let model = contents[withdrawIndex]
        
        let withDraw = MYGChatWithdrawCellModel()
        withDraw.isUsers = true
    
        
        var type: MYGIMMessageType = .chat
        var localId = 0
        var messageid = 0
        if let item = model as? MYGChatContentCellModel {
            type = .chat
            localId = item.localhostId
            messageid = item.messageId
            withDraw.message = item.content
        }
        
        if let item = model as? MYGChatImageCellModel {
            type = .image
            localId = item.localhostId
            messageid = item.messageId
        }
        
        if let item = model as? MYGChatPositionModel {
            type = .location
            localId = item.localhostId
            messageid = item.messageId
        }
        
        if let item = model as? MYGChatVoiceCellModel {
            type = .voice
            localId = item.localId
            messageid = item.messageId
        }
        
        socket.drawMessage(type, sessionId: sessionId, localId: localId, messageId: messageid)
        
        var isFind = false
        for model in chatHistoryModel {
            for data in model.message {
                for model in data.data {
                    if model.localhost_id == localId {
                        model.status = 5
                        isFind = true
                        break
                    }
                }
                
                if isFind {
                    break
                }
            }
            
            if isFind {
                break
            }
        }
        
        contents.insert(withDraw, at: withdrawIndex)
        contents.remove(at: withdrawIndex+1)
        
        tableView.reloadRows(at: [IndexPath(row: withdrawIndex, section: 0)], with: .automatic)
    }
    
    @objc
    private func withDrawMessage(_ not: Notification) {
        guard let userInfo = not.userInfo, let id = Int(userInfo["localhost_id"] as? String ?? "") else {
            return
        }
                
        guard let index = contents.firstIndex(where: { item in
            if let item = item as? MYGChatContentCellModel {
                return item.localhostId == id
            }
            
            if let item = item as? MYGChatImageCellModel {
                return item.localhostId == id
            }
            
            if let item = item as? MYGChatPositionModel {
                return item.localhostId == id
            }
            
            if let item = item as? MYGChatVoiceCellModel {
                return item.localId == id
            }
            
            return false
        }) else {
            return
        }
        
        let model = contents[index]
        
        let withDraw = MYGChatWithdrawCellModel()
        withDraw.isUsers = false
    
        if let item = model as? MYGChatContentCellModel {
            withDraw.message = item.content
        }
                
        var isFind = false
        for model in chatHistoryModel {
            for data in model.message {
                for model in data.data {
                    if model.localhost_id == id {
                        model.status = 5
                        isFind = true
                        break
                    }
                }
                
                if isFind {
                    break
                }
            }
            
            if isFind {
                break
            }
        }
        
        contents.insert(withDraw, at: index)
        contents.remove(at: index+1)
        
        tableView.reloadRows(at: [IndexPath(row: index, section: 0)], with: .automatic)
        
    }
}

extension MYGChatController: QMUIImagePreviewViewDelegate {
    func numberOfImages(in imagePreviewView: QMUIImagePreviewView!) -> UInt {
        return UInt(self.contents.count)
    }
    
    func imagePreviewView(_ imagePreviewView: QMUIImagePreviewView!, renderZoomImageView zoomImageView: QMUIZoomImageView!, at index: UInt) {
        guard let cell = tableView.cellForRow(at: IndexPath(item: Int(index), section: 0)) as? MYGChatPhotoCell else { return }
        zoomImageView.image = cell.contentImageView.image
    }
}
